
package com.hlkj.pay.service.merchant.impl;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.pojo.PageResult;
import com.hlkj.framework.common.util.collection.CollectionUtils;
import com.hlkj.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.hlkj.pay.dto.merchant.access.MerchantAccessAuthQueryDto;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.infrastructure.mapper.merchant.MerchantAccessAuthMapper;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessAuthDO;
import com.hlkj.pay.service.CommonSnFilterService;
import com.hlkj.pay.service.merchant.IMerchantAccessAuthService;
import com.hlkj.pay.util.OrderCodeUtil;

import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author HlpayTeam
 * @date 2024/09/25 13:33
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class MerchantAccessAuthServiceImpl extends CommonSnFilterService implements IMerchantAccessAuthService {

    private final MerchantAccessAuthMapper merchantAccessAuthMapper;

    private final OrderCodeUtil orderCodeUtil;

    @Override
    public void saveMerchantAccessAuth(List<MerchantAccessAuthDO> merchantAccessAuthList, List<MerchantAccessAuthDO> merchantAccessAuthDbs) {
        if (CollectionUtils.isEmpty(merchantAccessAuthList)) {
            return;
        }
        if (CollectionUtils.isEmpty(merchantAccessAuthDbs)) {
            addMerchantAccessAuth(merchantAccessAuthList);
            return;
        }
        Map<String, MerchantAccessAuthDO> accessAuthMap = merchantAccessAuthDbs.stream()
                .collect(Collectors.toMap(merchantInfoDO -> merchantInfoDO.getSubMchId(), Function.identity(), (t1, t2) -> t1));
        // 数据库存在 更新
        List<MerchantAccessAuthDO> addAccessAuthList = new ArrayList<>();
        List<MerchantAccessAuthDO> updateAccessAuthList = new ArrayList<>();
        merchantAccessAuthList.stream().forEach(merchantAccessAuthDO -> {
            MerchantAccessAuthDO merchantAccessAuthDO1 = null;
            if (merchantAccessAuthDO.getId() == null) {
                merchantAccessAuthDO1 = accessAuthMap.get(merchantAccessAuthDO.getSubMchId());
            }
            else {
                merchantAccessAuthDO1 = merchantAccessAuthDO;
            }
            if (merchantAccessAuthDO1 == null) {
                addAccessAuthList.add(merchantAccessAuthDO);
            }
            else {
                merchantAccessAuthDO1.setStatus(merchantAccessAuthDO.getStatus());
                merchantAccessAuthDO1.setAuthStatus(merchantAccessAuthDO.getAuthStatus());
                merchantAccessAuthDO1.setChannelJson(merchantAccessAuthDO.getChannelJson());
                merchantAccessAuthDO1.setMchId(merchantAccessAuthDO.getMchId());
                if (StringUtils.hasText(merchantAccessAuthDO.getSubMchId())) {
                    merchantAccessAuthDO1.setSubMchId(merchantAccessAuthDO.getSubMchId());
                }
                if (StringUtils.hasText(merchantAccessAuthDO.getSerialCode())) {
                    merchantAccessAuthDO1.setSerialCode(merchantAccessAuthDO.getSerialCode());
                }
                merchantAccessAuthDO1.setRejectReason(merchantAccessAuthDO.getRejectReason());
                merchantAccessAuthDO1.setRejectParam(merchantAccessAuthDO.getRejectParam());
                if (StringUtils.isEmpty(merchantAccessAuthDO1.getAuthUrl())) {
                    merchantAccessAuthDO1.setAuthUrl(merchantAccessAuthDO.getAuthUrl());
                }
                // if (MerchantEnum.MERCHANT_AUTH_STATUS.AUTH_FAIL.getCode().equals(merchantAccessAuthDO1.getStatus())) {
                //     merchantAccessAuthDO1.setState(CommonEnum.YES_NO_TYPE.NO.getCode());
                // }
                updateAccessAuthList.add(merchantAccessAuthDO1);
                merchantAccessAuthDO.setId(merchantAccessAuthDO1.getId());
            }
        });
        if (!CollectionUtils.isEmpty(addAccessAuthList)) {
            addMerchantAccessAuth(addAccessAuthList);
        }
        if (!CollectionUtils.isEmpty(updateAccessAuthList)) {
            updateMerchantAccessAuthList(updateAccessAuthList);
        }
    }

    @Override
    public void saveMerchantAccessAuth(List<MerchantAccessAuthDO> merchantAccessAuthList) {
        List<MerchantAccessAuthDO> merchantAccessAuthDbs = queryMerchantAccessAuth(merchantAccessAuthList.get(0).getAccessId());
        saveMerchantAccessAuth(merchantAccessAuthList, merchantAccessAuthDbs);
    }

    public String code() {
        return orderCodeUtil.orderNo("AUT", 8);
    }

    @Override
    public void saveMerchantAccessAuth(MerchantAccessAuthDO merchantAccessAuth) {
        merchantAccessAuth.setCode(code());
        if (MerchantEnum.MERCHANT_AUTH_STATUS.AUTH_FAIL.getCode().equals(merchantAccessAuth.getStatus())) {
            merchantAccessAuth.setState(CommonEnum.YES_NO_TYPE.NO.getCode());
        }
        merchantAccessAuthMapper.insert(merchantAccessAuth);
    }

    public void addMerchantAccessAuth(List<MerchantAccessAuthDO> merchantAccessAuthList) {
        // 进件AUT认证信息默认code赋值 唯一
        merchantAccessAuthList.forEach(auth -> {
            // code为空 默认赋值
            if (StrUtil.isEmpty(auth.getCode())) {
                auth.setCode(code());
            }
            if (MerchantEnum.MERCHANT_AUTH_STATUS.AUTH_FAIL.getCode().equals(auth.getStatus())) {
                auth.setState(CommonEnum.YES_NO_TYPE.NO.getCode());
            }
        });
        merchantAccessAuthMapper.insertBatch(merchantAccessAuthList);
    }

    @Override
    public List<MerchantAccessAuthDO> queryMerchantAccessAuth(Long accessId) {
        return merchantAccessAuthMapper.selectList(MerchantAccessAuthDO::getAccessId, accessId);
    }

    @Override
    public List<MerchantAccessAuthDO> queryMerchantAccessAuth(Long accessId, PayEnums.PAY_TYPE type) {
        LambdaQueryWrapperX<MerchantAccessAuthDO> queryWrapper = new LambdaQueryWrapperX<>();
        queryWrapper.eqIfPresent(MerchantAccessAuthDO::getAccessId, accessId);
        queryWrapper.eqIfPresent(MerchantAccessAuthDO::getType, type.getCode());
        return merchantAccessAuthMapper.selectList(queryWrapper);
    }

    @Override
    public MerchantAccessAuthDO routerAccessAuth(Long accessId, PayEnums.PAY_TYPE type) {
        MerchantAccessAuthQueryDto merchantAccessAuthQueryDto = new MerchantAccessAuthQueryDto();
        merchantAccessAuthQueryDto.setAccessId(accessId);
        merchantAccessAuthQueryDto.setType(type.getCode());
        merchantAccessAuthQueryDto.setLimitRouter(CommonEnum.YES_NO_TYPE.YES.getCode());
        LambdaQueryWrapperX<MerchantAccessAuthDO> lambdaQueryWrapperX = buildAuthWrapper(merchantAccessAuthQueryDto);
        lambdaQueryWrapperX.orderByDesc(MerchantAccessAuthDO::getId);
        lambdaQueryWrapperX.last("limit 1");
        return merchantAccessAuthMapper.selectOne(lambdaQueryWrapperX);
    }

    @Override
    public List<MerchantAccessAuthDO> routerAccessAuthList(Long accessId, PayEnums.PAY_TYPE type,Integer status,Integer limitRouter) {
        MerchantAccessAuthQueryDto merchantAccessAuthQueryDto = new MerchantAccessAuthQueryDto();
        merchantAccessAuthQueryDto.setAccessId(accessId);
        merchantAccessAuthQueryDto.setType(type.getCode());
        merchantAccessAuthQueryDto.setSortingFields("id");

        filterSn(merchantAccessAuthQueryDto);
        LambdaQueryWrapperX<MerchantAccessAuthDO> queryWrapper = new LambdaQueryWrapperX<>();
        queryWrapper.eqIfPresent(MerchantAccessAuthDO::getAccessId, merchantAccessAuthQueryDto.getAccessId());
        queryWrapper.eqIfPresent(MerchantAccessAuthDO::getDeleteFlag, CommonEnum.YES_NO_TYPE.NO.getCode());
        queryWrapper.eqIfPresent(MerchantAccessAuthDO::getType, merchantAccessAuthQueryDto.getType());
        queryWrapper.eqIfPresent(MerchantAccessAuthDO::getSn, merchantAccessAuthQueryDto.getSn());
        if(status != null){
            queryWrapper.eqIfPresent(MerchantAccessAuthDO::getState, status);
        }
        // if (limitRouter != null && !limitRouter.equals(CommonEnum.YES_NO_TYPE.NO.getCode())) {
        //     queryWrapper.eqIfPresent(MerchantAccessAuthDO::getLimitRouter, CommonEnum.YES_NO_TYPE.YES.getCode());
        // }
        return merchantAccessAuthMapper.selectList(queryWrapper);
    }

    @Override
    public MerchantAccessAuthDO queryMerchantAccessAuthById(Long id) {
        return merchantAccessAuthMapper.selectById(id);
    }

    @Override
    public MerchantAccessAuthDO queryMerchantAccessAuthByCode(String code) {
        return merchantAccessAuthMapper.selectOne(MerchantAccessAuthDO::getCode,code);
    }

    @Override
    public void updateMerchantAccessAuthList(List<MerchantAccessAuthDO> merchantAccessAuthList) {
        merchantAccessAuthMapper.updateBatch(merchantAccessAuthList, merchantAccessAuthList.size());
    }

    @Override
    public PageResult<MerchantAccessAuthDO> queryAuthPage(MerchantAccessAuthQueryDto merchantAccessAuthQueryDto) {
        return merchantAccessAuthMapper.selectPage(merchantAccessAuthQueryDto, buildAuthWrapper(merchantAccessAuthQueryDto));
    }

    @Override
    public List<MerchantAccessAuthDO> queryAuthList(MerchantAccessAuthQueryDto merchantAccessAuthQueryDto) {
        return merchantAccessAuthMapper.selectList(buildAuthWrapper(merchantAccessAuthQueryDto));
    }

    @Override
    public void updateMerchantAccessAuth(MerchantAccessAuthDO updateMerchantAppChannelDO) {
        merchantAccessAuthMapper.updateById(updateMerchantAppChannelDO);
    }

    @Override
    public void delAuth(Long id) {
        merchantAccessAuthMapper.deleteById(id);
    }

    @Override
    public MerchantAccessAuthDO queryMerchantAccessAuth(MerchantAccessAuthDO authDO) {
        LambdaQueryWrapperX<MerchantAccessAuthDO> queryWrapper = new LambdaQueryWrapperX<>();
        queryWrapper.eqIfPresent(MerchantAccessAuthDO::getAccessId, authDO.getAccessId());
        queryWrapper.eqIfPresent(MerchantAccessAuthDO::getSubMchId, authDO.getSubMchId());
        return merchantAccessAuthMapper.selectOne(queryWrapper);
    }

    public LambdaQueryWrapperX<MerchantAccessAuthDO> buildAuthWrapper(MerchantAccessAuthQueryDto merchantAccessAuthQueryDto) {
        filterSn(merchantAccessAuthQueryDto);
        LambdaQueryWrapperX<MerchantAccessAuthDO> queryWrapper = new LambdaQueryWrapperX<>();
        queryWrapper.eqIfPresent(MerchantAccessAuthDO::getAccessId, merchantAccessAuthQueryDto.getAccessId());
        queryWrapper.eqIfPresent(MerchantAccessAuthDO::getDeleteFlag, CommonEnum.YES_NO_TYPE.NO.getCode());
        queryWrapper.likeIfPresent(MerchantAccessAuthDO::getCode, merchantAccessAuthQueryDto.getCode());
        queryWrapper.eqIfPresent(MerchantAccessAuthDO::getWeight, merchantAccessAuthQueryDto.getWeight());
        queryWrapper.likeIfPresent(MerchantAccessAuthDO::getMchId, merchantAccessAuthQueryDto.getMchId());
        queryWrapper.likeIfPresent(MerchantAccessAuthDO::getSubMchId, merchantAccessAuthQueryDto.getSubMchId());
        queryWrapper.eqIfPresent(MerchantAccessAuthDO::getType, merchantAccessAuthQueryDto.getType());
        queryWrapper.likeIfPresent(MerchantAccessAuthDO::getSerialCode, merchantAccessAuthQueryDto.getSerialCode());
        queryWrapper.eqIfPresent(MerchantAccessAuthDO::getSn, merchantAccessAuthQueryDto.getSn());
        queryWrapper.inIfPresent(MerchantAccessAuthDO::getAccessId, merchantAccessAuthQueryDto.getAccessIdList());
        queryWrapper.eqIfPresent(MerchantAccessAuthDO::getLimitRouter, merchantAccessAuthQueryDto.getLimitRouter());

        if (merchantAccessAuthQueryDto.getState() != null) {
            // state=0 数据库null也可以查出
            if (merchantAccessAuthQueryDto.getState() == 0) {
                queryWrapper.and(wapper -> wapper.eq(MerchantAccessAuthDO::getState, 0).or().isNull(MerchantAccessAuthDO::getState));
            }
            else {
                queryWrapper.eqIfPresent(MerchantAccessAuthDO::getState, merchantAccessAuthQueryDto.getState());
            }
        }

        queryWrapper.geIfPresent(MerchantAccessAuthDO::getCreateTime, merchantAccessAuthQueryDto.getStartQueryTime());
        queryWrapper.leIfPresent(MerchantAccessAuthDO::getCreateTime, merchantAccessAuthQueryDto.getEndQueryTime());

        queryWrapper.gtIfPresent(MerchantAccessAuthDO::getId, merchantAccessAuthQueryDto.getMinId());
        queryWrapper.ltIfPresent(MerchantAccessAuthDO::getId, merchantAccessAuthQueryDto.getMaxId());
        return queryWrapper;
    }

}
